
package com.hlkj.pay.app.merchant.ext.impl.haike;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Repository;

import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.extension.annotation.Extension;
import com.hlkj.pay.app.merchant.ext.ChannelMerchantSettleExtPt;
import com.hlkj.pay.app.merchant.ext.MerchantExtConstant;
import com.hlkj.pay.app.merchant.ext.dto.settle.ChannelMerchantAccessSettleContext;
import com.hlkj.pay.app.merchant.ext.impl.haike.constant.HaikePayConstant;
import com.hlkj.pay.app.merchant.ext.impl.haike.dto.HaikePayConfig;
import com.hlkj.pay.app.merchant.ext.impl.haike.dto.resp.HaikeSettleBanlanceResp;
import com.hlkj.pay.app.merchant.ext.impl.haike.dto.resp.HaikeSettleWithdrawQueryResp;
import com.hlkj.pay.app.merchant.ext.impl.haike.dto.resp.HaikeSettleWithdrawResp;
import com.hlkj.pay.app.merchant.ext.impl.haike.handler.HaikePayCommonParamsHandle;
import com.hlkj.pay.dto.merchant.access.MerchantAccessBalanceDto;
import com.hlkj.pay.dto.order.notify.OrderSettleNotifyDto;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessInfoDO;
import com.hlkj.pay.infrastructure.model.order.OrderSettleDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.util.DateUtils;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * @author HlpayTeam
 * @date 2024/12/29 17:40
 */
@Slf4j
@Repository
@RequiredArgsConstructor
@Extension(bizId = MerchantExtConstant.CHANNEL_HAIKE_PAY)
public class HaikePayMerchantSettleExtPt implements ChannelMerchantSettleExtPt {

    private final HaikePayCommonParamsHandle haikePayCommonParamsHandle;

    @Override
    public void queryAccessBalance(ChannelMerchantAccessSettleContext merchantAccessSettleContext) {
        CommonResult<HaikePayConfig> haikePayConfigCommonResult = haikePayCommonParamsHandle.haikePayConfig(merchantAccessSettleContext.getProviderChannelConfig(),
                merchantAccessSettleContext.isTest());
        if (!haikePayConfigCommonResult.isSuccess()) {
            merchantAccessSettleContext.setRemark(haikePayConfigCommonResult.getMsg());
            merchantAccessSettleContext.setProcessStatus(false);
            return;
        }
        // 进件信息
        MerchantAccessInfoDO merchantAccessInfo = merchantAccessSettleContext.getMerchantAccessInfo();
        // 海科配置信息
        HaikePayConfig haikePayConfig = haikePayConfigCommonResult.getData();
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("merch_no", merchantAccessInfo.getSubMchId());
            log.info("海科余额查询 请求参数:{}", JSONUtil.toJsonStr(params));
            String result = haikePayCommonParamsHandle.requestPostApi(HaikePayConstant.ACCOUNT_BANLANCE_QUERY_URL,params,haikePayConfig);
            log.info("海科余额查询 返回参数:{}", result);
            if(StrUtil.isEmpty(result)){
                merchantAccessSettleContext.setProcessStatus(Boolean.FALSE);
                merchantAccessSettleContext.setRemark("海科余额查询请求失败");
                return;
            }

            HaikeSettleBanlanceResp settleBanlanceResp = JSONUtil.toBean(result,HaikeSettleBanlanceResp.class);
            if(HaikePayConstant.OK.equals(settleBanlanceResp.getReturn_code()) ){
                MerchantAccessBalanceDto merchantAccessBalanceDto = new MerchantAccessBalanceDto();
                // D1 可提现
                if(StrUtil.isNotEmpty(settleBanlanceResp.getMsa_balance())){
                    merchantAccessBalanceDto.setBalance(settleBanlanceResp.getMsa_balance());
                }
                // D0
                if(StrUtil.isNotEmpty(settleBanlanceResp.getMca_balance())){
                    merchantAccessBalanceDto.setAmountToBeSettled(settleBanlanceResp.getMca_balance());
                }
                merchantAccessSettleContext.setMerchantAccessBalanceDto(merchantAccessBalanceDto);
            }else{
                merchantAccessSettleContext.setProcessStatus(Boolean.FALSE);
                merchantAccessSettleContext.setRemark(settleBanlanceResp.getReturn_msg());
            }
        }
        catch (Exception e) {
            log.error("海科 商户余额查询 请求失败,失败信息 message: {}", e);
            merchantAccessSettleContext.setRemark("海科 商户余额查询 请求失败,失败信息" + e.getMessage());
            merchantAccessSettleContext.setProcessStatus(Boolean.FALSE);
        }
    }

    @Override
    public void submitAccessSettle(ChannelMerchantAccessSettleContext merchantAccessSettleContext) {
        CommonResult<HaikePayConfig> haikePayConfigCommonResult = haikePayCommonParamsHandle.haikePayConfig(merchantAccessSettleContext.getProviderChannelConfig(),
                merchantAccessSettleContext.isTest());
        if (!haikePayConfigCommonResult.isSuccess()) {
            merchantAccessSettleContext.setRemark(haikePayConfigCommonResult.getMsg());
            merchantAccessSettleContext.setProcessStatus(false);
            return;
        }
        // 结算订单
        OrderSettleDO orderSettleDO = merchantAccessSettleContext.getOrderSettleDO();
        // 进件信息
        MerchantAccessInfoDO merchantAccessInfo = merchantAccessSettleContext.getMerchantAccessInfo();
        // 海科配置信息
        HaikePayConfig haikePayConfig = haikePayConfigCommonResult.getData();
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("agent_no",haikePayConfig.getFtpName());
            params.put("merch_no", merchantAccessInfo.getSubMchId());
            params.put("agent_apply_no", orderSettleDO.getPayOrderNo());
            params.put("withdraw_amount", NumberUtil.roundStr(orderSettleDO.getAmount().doubleValue(),2));

            log.info("海科手动提现 请求参数:{}", JSONUtil.toJsonStr(params));
            String result = haikePayCommonParamsHandle.requestPostApi(HaikePayConstant.ACCOUNT_MANAUL_WITHDRAW_URL,params,haikePayConfig);
            log.info("海科手动提现 返回参数:{}", result);
            if(StrUtil.isEmpty(result)){
                merchantAccessSettleContext.setProcessStatus(Boolean.FALSE);
                merchantAccessSettleContext.setRemark("海科手动提现请求失败");
                return;
            }

            HaikeSettleWithdrawResp withdrawResp = JSONUtil.toBean(result,HaikeSettleWithdrawResp.class);
            OrderSettleDO updatePayOrderDO = new OrderSettleDO();
            if(HaikePayConstant.OK.equals(withdrawResp.getReturn_code()) ){
                updatePayOrderDO.setOrderStatus(MerchantEnum.MERCHANT_ACCESS_AMOUNT_STATUS.DOING.getCode());
                updatePayOrderDO.setSettleFee(new BigDecimal(withdrawResp.getWithdraw_fee()));
            }else{
                updatePayOrderDO.setOrderStatus(MerchantEnum.MERCHANT_ACCESS_AMOUNT_STATUS.FAIL.getCode());
                merchantAccessSettleContext.setProcessStatus(Boolean.FALSE);
                merchantAccessSettleContext.setRemark(withdrawResp.getReturn_msg());
            }
            merchantAccessSettleContext.setUpdateAccessAmountOrderDO(updatePayOrderDO);
        }
        catch (Exception e) {
            log.error("海科手动提现请求失败 message:{}", e);
            merchantAccessSettleContext.setRemark("海科手动提现请求失败,失败信息" + e.getMessage());
            merchantAccessSettleContext.setProcessStatus(Boolean.FALSE);
        }
    }

    @Override
    public void queryAccessSettle(ChannelMerchantAccessSettleContext merchantAccessSettleContext) {
        CommonResult<HaikePayConfig> haikePayConfigCommonResult = haikePayCommonParamsHandle.haikePayConfig(merchantAccessSettleContext.getProviderChannelConfig(),
                merchantAccessSettleContext.isTest());
        if (!haikePayConfigCommonResult.isSuccess()) {
            merchantAccessSettleContext.setRemark(haikePayConfigCommonResult.getMsg());
            merchantAccessSettleContext.setProcessStatus(false);
            return;
        }
        // 结算订单
        OrderSettleDO orderSettleDO = merchantAccessSettleContext.getOrderSettleDO();
        // 进件信息
        MerchantAccessInfoDO merchantAccessInfo = merchantAccessSettleContext.getMerchantAccessInfo();
        // 海科配置信息
        HaikePayConfig haikePayConfig = haikePayConfigCommonResult.getData();
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("merch_no", merchantAccessInfo.getSubMchId());
            params.put("out_apply_no", orderSettleDO.getPayOrderNo());
            // 手动提现查询
            params.put("settlement_cycle","MANAUL");
            log.info("海科手动提现查询 请求参数:{}", JSONUtil.toJsonStr(params));
            String result = haikePayCommonParamsHandle.requestPostApi(HaikePayConstant.ACCOUNT_WITHDRAW_QUERY_URL,params,haikePayConfig);
            log.info("海科手动提现查询 返回参数:{}", result);
            if(StrUtil.isEmpty(result)){
                merchantAccessSettleContext.setProcessStatus(Boolean.FALSE);
                merchantAccessSettleContext.setRemark("海科手动提现查询请求失败");
                return;
            }

            HaikeSettleWithdrawQueryResp withdrawQueryResp = JSONUtil.toBean(result,HaikeSettleWithdrawQueryResp.class);
            OrderSettleDO updatePayOrderDO = new OrderSettleDO();
            if(HaikePayConstant.OK.equals(withdrawQueryResp.getReturn_code()) ){
                updatePayOrderDO.setSettleFee(new BigDecimal(withdrawQueryResp.getWithdraw_fee()));
                updatePayOrderDO.setOrderStatus(MerchantEnum.MERCHANT_ACCESS_AMOUNT_STATUS.SUCCESS.getCode());
                updatePayOrderDO.setSuccessTime(DateUtils.shanghaiLocalDate(withdrawQueryResp.getSuccess_time(), DatePattern.NORM_DATETIME_PATTERN));
            }else{
                updatePayOrderDO.setOrderStatus(MerchantEnum.MERCHANT_ACCESS_AMOUNT_STATUS.FAIL.getCode());
                updatePayOrderDO.setRemark(withdrawQueryResp.getReturn_msg());
            }
            merchantAccessSettleContext.setUpdateAccessAmountOrderDO(updatePayOrderDO);
        }
        catch (Exception e) {
            log.error("海科手动提现查询请求失败 message:{}", e);
            merchantAccessSettleContext.setRemark("海科手动提现查询请求失败,失败信息" + e.getMessage());
            merchantAccessSettleContext.setProcessStatus(Boolean.FALSE);
        }
    }

    @Override
    public CommonResult<OrderSettleNotifyDto> orderStatusParse(HttpServletRequest request, ProviderChannelConfigDO providerChannelConfigDO) {
        return CommonResult.success();
    }
}
